1
|
|
|
"use strict"; |
2
|
|
|
|
3
|
|
|
const fs = require ('fs') |
4
|
|
|
const log = require ('ololog') |
5
|
|
|
const ansi = require ('ansicolor').nice |
|
|
|
|
6
|
|
|
|
7
|
|
|
//----------------------------------------------------------------------------- |
8
|
|
|
|
9
|
|
|
function regexAll (text, array) { |
10
|
|
|
for (let i in array) { |
11
|
|
|
let regex = array[i][0] |
12
|
|
|
regex = typeof regex == 'string' ? new RegExp (regex, 'g') : new RegExp (regex) |
13
|
|
|
text = text.replace (regex, array[i][1]) |
14
|
|
|
} |
15
|
|
|
return text |
16
|
|
|
} |
17
|
|
|
|
18
|
|
|
//----------------------------------------------------------------------------- |
19
|
|
|
|
20
|
|
|
let ccxtjs = fs.readFileSync ('ccxt.js', 'utf8') |
21
|
|
|
let contents = ccxtjs.match (/\/\/====(?:[\s\S]+?)\/\/====/) [0] |
22
|
|
|
let exchanges |
23
|
|
|
let regex = /^var ([\S]+) =\s*(?:extend\s*\(([^\,]+)\,\s*)?{([\s\S]+?)^}/gm // exchange class |
24
|
|
|
|
25
|
|
|
let python = [] |
26
|
|
|
let pythonAsync = [] |
27
|
|
|
let php = [] |
28
|
|
|
|
29
|
|
|
//----------------------------------------------------------------------------- |
30
|
|
|
|
31
|
|
|
while (exchanges = regex.exec (contents)) { |
32
|
|
|
|
33
|
|
|
let id = exchanges[1] |
34
|
|
|
|
35
|
|
|
let parent = exchanges[2] |
36
|
|
|
|
37
|
|
|
let all = exchanges[3].trim ().split (/\,\s*\n\s*\n/) |
38
|
|
|
let params = ' ' + all[0] |
39
|
|
|
let methods = all.slice (1) |
40
|
|
|
|
41
|
|
|
let py = [] |
42
|
|
|
let pyAsync = [] |
43
|
|
|
let ph = [] |
44
|
|
|
|
45
|
|
|
params = params.split ("\n") |
46
|
|
|
|
47
|
|
|
let pyParams = params |
48
|
|
|
.join ("\n ") |
49
|
|
|
.replace (/ true/g, ' True') |
50
|
|
|
.replace (/ false/g, ' False') |
51
|
|
|
.replace (/ undefined/g, ' None') |
52
|
|
|
.replace (/ \/\//g, ' #') |
53
|
|
|
.replace (/\{ /g, '{') // PEP8 E201 |
54
|
|
|
.replace (/\[ /g, '[') // PEP8 E201 |
55
|
|
|
.replace (/([^\s]+) \]/g, '$1]') // PEP8 E202 |
56
|
|
|
.replace (/([^\s]+) \}\,/g, '$1},') // PEP8 E202 |
57
|
|
|
|
58
|
|
|
function pyAddClass (py) { |
|
|
|
|
59
|
|
|
py.push ('') |
60
|
|
|
py.push ('class ' + id + ' (' + (parent ? parent : 'Exchange') + '):') |
61
|
|
|
py.push ('') |
62
|
|
|
py.push (' def __init__(self, config={}):') |
63
|
|
|
py.push (' params = {') |
64
|
|
|
py.push (' ' + pyParams + ((all.length > 1) ? ',' : '')) |
65
|
|
|
py.push (' }') |
66
|
|
|
py.push (' params.update(config)') |
67
|
|
|
py.push (' super(' + id + ', self).__init__(params)') |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
pyAddClass (py); |
71
|
|
|
pyAddClass (pyAsync); |
72
|
|
|
|
73
|
|
|
let phParams = params |
74
|
|
|
.join ("\n ") |
75
|
|
|
.replace (/ undefined/g, ' null') |
76
|
|
|
.replace (/': /g, "' => ") |
77
|
|
|
.replace (/ {/g, ' array (') |
78
|
|
|
.replace (/ \[/g, ' array (') |
79
|
|
|
.replace (/\}([\,\n]|$)/g, ')$1') |
80
|
|
|
.replace (/\]/g, ')') |
81
|
|
|
|
82
|
|
|
ph.push ('') |
83
|
|
|
ph.push ('class ' + id + ' extends ' + (parent ? parent : 'Exchange') + ' {') |
84
|
|
|
ph.push ('') |
85
|
|
|
ph.push (' public function __construct ($options = array ()) {') |
86
|
|
|
ph.push (' parent::__construct (array_merge(array (') |
87
|
|
|
ph.push (' ' + phParams + ((all.length > 1) ? ',' : '')) |
88
|
|
|
ph.push (' ), $options));') |
89
|
|
|
ph.push (' }') |
90
|
|
|
|
91
|
|
|
for (let i = 0; i < methods.length; i++) { |
92
|
|
|
let part = methods[i].trim () |
93
|
|
|
let lines = part.split ("\n") |
94
|
|
|
let header = lines[0].trim () |
95
|
|
|
let regex2 = /(async |)([\S]+)\s\(([^)]*)\)\s*{/g // exchange method |
96
|
|
|
let matches = regex2.exec (header) |
97
|
|
|
let keyword = matches[1] |
98
|
|
|
let method = matches[2] |
99
|
|
|
let args = matches[3].trim () |
100
|
|
|
|
101
|
|
|
method = method.replace ('fetchBalance', 'fetch_balance') |
102
|
|
|
// .replace ('fetchCategories', 'fetch_categories') |
103
|
|
|
.replace ('loadMarkets', 'load_markets') |
104
|
|
|
.replace ('fetchMarkets', 'fetch_markets') |
105
|
|
|
.replace ('fetchOrderBook', 'fetch_order_book') |
106
|
|
|
.replace ('fetchOHLCV', 'fetch_ohlcv') |
107
|
|
|
.replace ('parseOHLCVs', 'parse_ohlcvs') |
108
|
|
|
.replace ('parseOHLCV', 'parse_ohlcv') |
109
|
|
|
.replace ('fetchTickers', 'fetch_tickers') |
110
|
|
|
.replace ('fetchTicker', 'fetch_ticker') |
111
|
|
|
.replace ('parseTicker', 'parse_ticker') |
112
|
|
|
.replace ('parseTradesData', 'parse_trades_data') |
113
|
|
|
.replace ('parseTrades', 'parse_trades') |
114
|
|
|
.replace ('parseTrade', 'parse_trade') |
115
|
|
|
.replace ('parseOrderBook', 'parse_order_book') |
116
|
|
|
.replace ('parseBidAsks', 'parse_bidasks') |
117
|
|
|
.replace ('parseBidAsk', 'parse_bidask') |
118
|
|
|
.replace ('parseOrders', 'parse_orders') |
119
|
|
|
.replace ('parseOrder', 'parse_order') |
120
|
|
|
.replace ('fetchTrades', 'fetch_trades') |
121
|
|
|
.replace ('fetchOrderStatus', 'fetch_order_status') |
122
|
|
|
.replace ('fetchOrderTrades', 'fetch_order_trades') |
123
|
|
|
.replace ('fetchOrders', 'fetch_orders') |
124
|
|
|
.replace ('fetchOrder', 'fetch_order') |
125
|
|
|
.replace ('fetchOpenOrders', 'fetch_open_orders') |
126
|
|
|
.replace ('fetchMyTrades', 'fetch_my_trades') |
127
|
|
|
.replace ('fetchAllMyTrades', 'fetch_all_my_trades') |
128
|
|
|
.replace ('createOrder', 'create_order') |
129
|
|
|
.replace ('cancelOrder', 'cancel_order') |
130
|
|
|
.replace ('signIn', 'sign_in') |
131
|
|
|
|
132
|
|
|
args = args.length ? args.split (',').map (x => x.trim ()) : [] |
133
|
|
|
|
134
|
|
|
let phArgs = args.join (', $').trim () |
135
|
|
|
phArgs = phArgs.length ? ('$' + phArgs) : '' |
136
|
|
|
|
137
|
|
|
let pyArgs = args.map (x => x.replace (' = ', '=')).join (', ') |
138
|
|
|
|
139
|
|
|
let variables = args.map (arg => arg.split ('=').map (x => x.trim ()) [0]) |
140
|
|
|
|
141
|
|
|
let body = lines.slice (1, -1).join ("\n") |
142
|
|
|
|
143
|
|
|
let regex3 = /[^a-zA-Z0-9_]let\s+(?:\[([^\]]+)\]|([a-zA-Z0-9_]+))/g // local variables |
144
|
|
|
|
145
|
|
|
let localVariablesMatches |
146
|
|
|
while (localVariablesMatches = regex3.exec (body)) { |
147
|
|
|
let m = localVariablesMatches[1] ? localVariablesMatches[1] : localVariablesMatches[2] |
148
|
|
|
m = m.trim ().split (', ') |
149
|
|
|
m.forEach (x => variables.push (x.trim ())) |
150
|
|
|
variables.push (localVariablesMatches[1]) |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
let phVarsRegex = variables.map (x => [ "([^$$a-zA-Z0-9\\.\\>'_])" + x + "([^a-zA-Z0-9'_])", '$1$$' + x + '$2' ]) |
154
|
|
|
|
155
|
|
|
let pyRegex = [ |
156
|
|
|
[ /typeof\s+([^\s\[]+)(?:\s|\[(.+?)\])\s+\=\=\s+\'undefined\'/g, '$1[$2] is None' ], |
157
|
|
|
[ /undefined/g, 'None' ], |
158
|
|
|
[ /this\.stringToBinary\s*\((.*)\)/g, '$1' ], |
159
|
|
|
[ /this\.stringToBase64\s/g, 'base64.b64encode' ], |
160
|
|
|
[ /this\.base64ToBinary\s/g, 'base64.b64decode' ], |
161
|
|
|
[ /\.safeFloat\s/g, '.safe_float'], |
162
|
|
|
[ /\.binaryConcat\s/g, '.binary_concat'], |
163
|
|
|
[ /\.binaryToString\s/g, '.binary_to_string' ], |
164
|
|
|
[ /\.implodeParams\s/g, '.implode_params'], |
165
|
|
|
[ /\.extractParams\s/g, '.extract_params'], |
166
|
|
|
[ /\.parseOHLCVs/g, '.parse_ohlcvs'], |
167
|
|
|
[ /\.parseOHLCV/g, '.parse_ohlcv'], |
168
|
|
|
[ /\.parseTicker\s/g, '.parse_ticker'], |
169
|
|
|
[ /\.parseTradesData\s/g, '.parse_trades_data'], |
170
|
|
|
[ /\.parseTrades\s/g, '.parse_trades'], |
171
|
|
|
[ /\.parseTrade\s/g, '.parse_trade'], |
172
|
|
|
[ /\.parseOrderBook\s/g, '.parse_order_book'], |
173
|
|
|
[ /\.parseBidAsks\s/g, '.parse_bidasks'], |
174
|
|
|
[ /\.parseBidAsk\s/g, '.parse_bidask'], |
175
|
|
|
[ /\.parseOrders\s/g, '.parse_orders'], |
176
|
|
|
[ /\.parseOrder\s/g, '.parse_order'], |
177
|
|
|
[ /\.indexBy\s/g, '.index_by'], |
178
|
|
|
[ /\.sortBy\s/g, '.sort_by'], |
179
|
|
|
[ /\.marketIds\s/g, '.market_ids'], |
180
|
|
|
[ /\.marketId\s/g, '.market_id'], |
181
|
|
|
[ /\.fetchOrderStatus\s/g, '.fetch_order_status'], |
182
|
|
|
[ /\.fetchOpenOrders\s/g, '.fetch_open_orders'], |
183
|
|
|
[ /\.fetchOrders\s/g, '.fetch_orders'], |
184
|
|
|
[ /\.loadMarkets\s/g, '.load_markets'], |
185
|
|
|
[ /\.encodeURIComponent\s/g, '.encode_uri_component'], |
186
|
|
|
// [ /this\.urlencode\s/g, '_urlencode.urlencode ' ], // use self.urlencode instead |
187
|
|
|
[ /this\./g, 'self.' ], |
188
|
|
|
[ /([^a-zA-Z\'])this([^a-zA-Z])/g, '$1self$2' ], |
189
|
|
|
[ /([^a-zA-Z0-9_])let\s\[\s*([^\]]+)\s\]/g, '$1$2' ], |
190
|
|
|
[ /([^a-zA-Z0-9_])let\s/g, '$1' ], |
191
|
|
|
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ], |
192
|
|
|
[ /Object\.keys\s*\((.*)\)/g, 'list($1.keys())' ], |
193
|
|
|
[ /\[([^\]]+)\]\.join\s*\(([^\)]+)\)/g, "$2.join([$1])" ], |
194
|
|
|
[ /hash \(([^,]+)\, \'(sha[0-9])\'/g, "hash($1, '$2'" ], |
195
|
|
|
[ /hmac \(([^,]+)\, ([^,]+)\, \'(md5)\'/g, 'hmac($1, $2, hashlib.$3' ], |
196
|
|
|
[ /hmac \(([^,]+)\, ([^,]+)\, \'(sha[0-9]+)\'/g, 'hmac($1, $2, hashlib.$3' ], |
197
|
|
|
[ /throw new ([\S]+) \((.*)\)/g, 'raise $1($2)'], |
198
|
|
|
[ /throw ([\S]+)/g, 'raise $1'], |
199
|
|
|
[ /try {/g, 'try:'], |
200
|
|
|
[ /\}\s+catch \(([\S]+)\) {/g, 'except Exception as $1:'], |
201
|
|
|
[ /([\s\(])extend(\s)/g, '$1self.extend$2' ], |
202
|
|
|
[ /\} else if/g, 'elif' ], |
203
|
|
|
[ /if\s+\((.*)\)\s+\{/g, 'if $1:' ], |
204
|
|
|
[ /if\s+\((.*)\)\s*[\n]/g, "if $1:\n" ], |
205
|
|
|
[ /\}\s*else\s*\{/g, 'else:' ], |
206
|
|
|
[ /else\s*[\n]/g, "else:\n" ], |
207
|
|
|
[ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(?:\<=|\>=|<|>)\s*(.*)\.length\s*\;[^\)]+\)\s*{/g, 'for $1 in range($2, len($3)):'], |
208
|
|
|
[ /\s\|\|\s/g, ' or ' ], |
209
|
|
|
[ /\s\&\&\s/g, ' and ' ], |
210
|
|
|
[ /\!([^\=])/g, 'not $1'], |
211
|
|
|
[ /([^\s]+)\.length/g, 'len($1)' ], |
212
|
|
|
[ /\.push\s*\(([\s\S]+?)\);/g, '.append($1);' ], |
213
|
|
|
[ /^\s*}\s*[\n]/gm, '' ], |
214
|
|
|
[ /;/g, '' ], |
215
|
|
|
[ /\.toUpperCase\s*/g, '.upper' ], |
216
|
|
|
[ /\.toLowerCase\s*/g, '.lower' ], |
217
|
|
|
[ /JSON\.stringify\s*/g, 'json.dumps' ], |
218
|
|
|
// [ /\'%([^\']+)\'\.sprintf\s*\(([^\)]+)\)/g, "'{:$1}'.format($2)" ], |
219
|
|
|
[ /([^\s]+)\.toFixed\s*\(([^\)]+)\)/g, "'{:.$2f}'.format($1)" ], |
220
|
|
|
[ /parseFloat\s*/g, 'float'], |
221
|
|
|
[ /parseInt\s*/g, 'int'], |
222
|
|
|
[ /self\[([^\]+]+)\]/g, 'getattr(self, $1)' ], |
223
|
|
|
[ /([^\s]+)\.slice \(([^\,\)]+)\,\s?([^\)]+)\)/g, '$1[$2:$3]' ], |
224
|
|
|
[ /([^\s]+)\.slice \(([^\)\:]+)\)/g, '$1[$2:]' ], |
225
|
|
|
[ /Math\.floor\s*\(([^\)]+)\)/g, 'int(math.floor($1))' ], |
226
|
|
|
[ /Math\.abs\s*\(([^\)]+)\)/g, 'abs($1)' ], |
227
|
|
|
[ /Math\.round\s*\(([^\)]+)\)/g, 'int(round($1))' ], |
228
|
|
|
[ /(\([^\)]+\)|[^\s]+)\s*\?\s*(\([^\)]+\)|[^\s]+)\s*\:\s*(\([^\)]+\)|[^\s]+)/g, '$2 if $1 else $3'], |
229
|
|
|
[/ \/\//g, ' #' ], |
230
|
|
|
[ /\.indexOf/g, '.find'], |
231
|
|
|
[ /\strue/g, ' True'], |
232
|
|
|
[ /\sfalse/g, ' False'], |
233
|
|
|
[ /\(([^\s]+)\sin\s([^\)]+)\)/g, '($1 in list($2.keys()))' ], |
234
|
|
|
[ /([^\s]+\s*\(\))\.toString\s+\(\)/g, 'str($1)' ], |
235
|
|
|
[ /([^\s]+)\.toString \(\)/g, 'str($1)' ], |
236
|
|
|
[ /([^\s]+)\.join\s*\(\s*([^\)\[\]]+?)\s*\)/g, '$2.join($1)' ], |
237
|
|
|
[ /Math\.(max|min)\s/g, '$1' ], |
238
|
|
|
[ /console\.log\s/g, 'print'], |
239
|
|
|
[ /process\.exit\s+/g, 'sys.exit'], |
240
|
|
|
[ /([^+=\s]+) \(/g, '$1(' ], // PEP8 E225 remove whitespaces before left ( round bracket |
241
|
|
|
[ /\[ /g, '[' ], // PEP8 E201 remove whitespaces after left [ square bracket |
242
|
|
|
[ /\{ /g, '{' ], // PEP8 E201 remove whitespaces after left { bracket |
243
|
|
|
[ /([^\s]+) \]/g, '$1]' ], // PEP8 E202 remove whitespaces before right ] square bracket |
244
|
|
|
[ /([^\s]+) \}/g, '$1}' ], // PEP8 E202 remove whitespaces before right } bracket |
245
|
|
|
] |
246
|
|
|
|
247
|
|
|
let phRegex = [ |
248
|
|
|
[ /typeof\s+([^\s\[]+)(?:\s|\[(.+?)\])\s+\=\=\s+\'undefined\'/g, '$1[$2] == null' ], |
249
|
|
|
[ /undefined/g, 'null' ], |
250
|
|
|
[ /this\.extend/g, 'array_merge' ], |
251
|
|
|
[ /this\.stringToBinary\s*\((.*)\)/g, '$1' ], |
252
|
|
|
[ /this\.stringToBase64/g, 'base64_encode' ], |
253
|
|
|
[ /this\.base64ToBinary/g, 'base64_decode' ], |
254
|
|
|
[ /\.safeFloat/g, '.safe_float'], |
255
|
|
|
[ /\.parseOHLCVs/g, '.parse_ohlcvs'], |
256
|
|
|
[ /\.parseOHLCV/g, '.parse_ohlcv'], |
257
|
|
|
[ /\.parseTicker/g, '.parse_ticker'], |
258
|
|
|
[ /\.parseTradesData/g, '.parse_trades_data'], |
259
|
|
|
[ /\.parseTrades/g, '.parse_trades'], |
260
|
|
|
[ /\.parseTrade/g, '.parse_trade'], |
261
|
|
|
[ /\.parseOrderBook/g, '.parse_order_book'], |
262
|
|
|
[ /\.parseBidAsks/g, '.parse_bidasks'], |
263
|
|
|
[ /\.parseBidAsk/g, '.parse_bidask'], |
264
|
|
|
[ /\.binaryConcat/g, '.binary_concat'], |
265
|
|
|
[ /\.binaryToString/g, '.binary_to_string' ], |
266
|
|
|
[ /\.implodeParams/g, '.implode_params'], |
267
|
|
|
[ /\.extractParams/g, '.extract_params'], |
268
|
|
|
[ /\.indexBy/g, '.index_by'], |
269
|
|
|
[ /\.sortBy/g, '.sort_by'], |
270
|
|
|
[ /\.marketIds/g, '.market_ids'], |
271
|
|
|
[ /\.marketId/g, '.market_id'], |
272
|
|
|
[ /\.fetchOrderStatus/g, '.fetch_order_status'], |
273
|
|
|
[ /\.fetchOpenOrders/g, '.fetch_open_orders'], |
274
|
|
|
[ /\.fetchOrders/g, '.fetch_orders'], |
275
|
|
|
[ /\.parseOrders/g, '.parse_orders'], |
276
|
|
|
[ /\.parseOrder/g, '.parse_order'], |
277
|
|
|
[ /\.loadMarkets/g, '.load_markets'], |
278
|
|
|
[ /\.encodeURIComponent/g, '.encode_uri_component'], |
279
|
|
|
[ /this\./g, '$this->' ], |
280
|
|
|
[ / this;/g, ' $this;' ], |
281
|
|
|
[ /([^'])this_\./g, '$1$this_->' ], |
282
|
|
|
[ /\{\}/g, 'array ()' ], |
283
|
|
|
[ /\[\]/g, 'array ()' ], |
284
|
|
|
[ /\{([^\n\}]+)\}/g, 'array ($1)' ], |
285
|
|
|
[ /([^a-zA-Z0-9_])let\s\[\s*([^\]]+)\s\]/g, '$1list ($2)' ], |
286
|
|
|
[ /([^a-zA-Z0-9_])let\s/g, '$1' ], |
287
|
|
|
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ], |
288
|
|
|
[ /Object\.keys\s*\((.*)\)/g, 'array_keys ($1)' ], |
289
|
|
|
[ /([^\s]+\s*\(\))\.toString \(\)/g, '(string) $1' ], |
290
|
|
|
[ /([^\s]+)\.toString \(\)/g, '(string) $1' ], |
291
|
|
|
[ /throw new Error \((.*)\)/g, 'throw new \\Exception ($1)'], |
292
|
|
|
[ /throw new ([\S]+) \((.*)\)/g, 'throw new $1 ($2)'], |
293
|
|
|
[ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(\<=|\>=|<|>)\s*(.*)\.length\s*\;([^\)]+)\)\s*{/g, 'for ($1 = $2; $1 $3 count ($4);$5) {'], |
294
|
|
|
[ /([^\s]+)\.length\;/g, 'count ($1);' ], |
295
|
|
|
[ /([^\s]+)\.length/g, 'strlen ($1)' ], |
296
|
|
|
[ /\.push\s*\(([\s\S]+?)\)\;/g, '[] = $1;' ], |
297
|
|
|
[ /(\s)await(\s)/g, '$1' ], |
298
|
|
|
[ /([\S])\: /g, '$1 => ' ], |
299
|
|
|
[ /\{([^\;\{]+?)\}([^\s])/g, 'array ($1)$2' ], |
300
|
|
|
[ /\[\s*([^\]]+?)\s*\]\.join\s*\(\s*([^\)]+?)\s*\)/g, "implode ($2, array ($1))" ], |
301
|
|
|
[ /\[\s([^\]]+?)\s\]/g, 'array ($1)' ], |
302
|
|
|
[ /JSON\.stringify/g, 'json_encode' ], |
303
|
|
|
// [ /\'([^\']+)\'\.sprintf\s*\(([^\)]+)\)/g, "sprintf ('$1', $2)" ], |
304
|
|
|
[ /([^\s]+)\.toFixed\s*\(([^\)]+)\)/g, "sprintf ('%$2f', $1)" ], |
305
|
|
|
[ /parseFloat\s/g, 'floatval '], |
306
|
|
|
[ /parseInt\s/g, 'intval '], |
307
|
|
|
[ / \+ /g, ' . ' ], |
308
|
|
|
[ / \+\= /g, ' .= ' ], |
309
|
|
|
[ /([^\s]+(?:\s*\(.+\))?)\.toUpperCase\s*\(\)/g, 'strtoupper ($1)' ], |
310
|
|
|
[ /([^\s]+(?:\s*\(.+\))?)\.toLowerCase\s*\(\)/g, 'strtolower ($1)' ], |
311
|
|
|
[ /([^\s]+(?:\s*\(.+\))?)\.replace\s*\(([^\)]+)\)/g, 'str_replace ($2, $1)' ], |
312
|
|
|
[ /this\[([^\]+]+)\]/g, '$$this->$$$1' ], |
313
|
|
|
[ /([^\s]+).slice \(([^\)\:]+)\)/g, 'mb_substr ($1, $2)' ], |
314
|
|
|
[ /([^\s]+).slice \(([^\,\)]+)\,\s*([^\)]+)\)/g, 'mb_substr ($1, $2, $3)' ], |
315
|
|
|
[ /([^\s]+).split \(([^\,]+?)\)/g, 'explode ($2, $1)' ], |
316
|
|
|
[ /Math\.floor\s*\(([^\)]+)\)/g, '(int) floor ($1)' ], |
317
|
|
|
[ /Math\.abs\s*\(([^\)]+)\)/g, 'abs ($1)' ], |
318
|
|
|
[ /Math\.round\s*\(([^\)]+)\)/g, '(int) round ($1)' ], |
319
|
|
|
[ /([^\(\s]+)\s+%\s+([^\s\)]+)/g, 'fmod ($1, $2)' ], |
320
|
|
|
[ /\(([^\s]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0\)/g, '(mb_strpos ($1, $2) !== false)' ], |
321
|
|
|
[ /([^\s]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0/g, 'mb_strpos ($1, $2) !== false' ], |
322
|
|
|
[ /([^\s]+)\.indexOf\s*\(([^\)]+)\)/g, 'mb_strpos ($1, $2)' ], |
323
|
|
|
[ /\(([^\s]+)\sin\s([^\)]+)\)/g, '(array_key_exists ($1, $2))' ], |
324
|
|
|
[ /([^\s]+)\.join\s*\(\s*([^\)]+?)\s*\)/g, 'implode ($2, $1)' ], |
325
|
|
|
[ /Math\.(max|min)/g, '$1' ], |
326
|
|
|
[ /console\.log/g, 'var_dump'], |
327
|
|
|
[ /process\.exit/g, 'exit'], |
328
|
|
|
] |
329
|
|
|
|
330
|
|
|
let pyRegexSync = pyRegex.concat ([ |
331
|
|
|
[ /(\s)await(\s)/g, '$1' ] |
332
|
|
|
]) |
333
|
|
|
|
334
|
|
|
let pyBody = regexAll (body, pyRegexSync) |
335
|
|
|
let pyBodyAsync = regexAll (body, pyRegex) |
336
|
|
|
|
337
|
|
|
// special case for Python OrderedDicts |
338
|
|
|
|
339
|
|
|
let orderedRegex = /\.ordered\s+\(\{([^\}]+)\}\)/g |
340
|
|
|
let orderedMatches = undefined |
|
|
|
|
341
|
|
|
while (orderedMatches = orderedRegex.exec (pyBody)) { |
342
|
|
|
let replaced = orderedMatches[1].replace (/^(\s+)([^\:]+)\:\s*([^\,]+)\,$/gm, '$1($2, $3),') |
343
|
|
|
pyBody = pyBody.replace (orderedRegex, '\.ordered ([' + replaced + '])') |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
let pyString = 'def ' + method + '(self' + (pyArgs.length ? ', ' + pyArgs.replace (/undefined/g, 'None').replace (/false/g, 'False').replace (/true/g, 'True') : '') + '):' |
347
|
|
|
|
348
|
|
|
py.push (''); |
349
|
|
|
py.push (' ' + pyString); |
350
|
|
|
py.push (pyBody); |
351
|
|
|
|
352
|
|
|
pyAsync.push (''); |
353
|
|
|
pyAsync.push (' ' + keyword + pyString); |
354
|
|
|
pyAsync.push (pyBodyAsync); |
355
|
|
|
|
356
|
|
|
let phBody = regexAll (body, phRegex.concat (phVarsRegex)) |
357
|
|
|
|
358
|
|
|
ph.push (''); |
359
|
|
|
ph.push (' public function ' + method + ' (' + phArgs.replace (/undefined/g, 'null').replace ('{}', 'array ()') + ') {'); |
360
|
|
|
ph.push (phBody); |
361
|
|
|
ph.push (' }') |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
py.push ('') |
365
|
|
|
pyAsync.push ('') |
366
|
|
|
|
367
|
|
|
python.push (py.join ("\n")) |
368
|
|
|
pythonAsync.push (pyAsync.join ("\n")) |
369
|
|
|
|
370
|
|
|
ph.push ('}') |
371
|
|
|
ph.push ('') |
372
|
|
|
|
373
|
|
|
php.push (ph.join ("\n")) |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
//----------------------------------------------------------------------------- |
377
|
|
|
|
378
|
|
|
function transpile (oldName, newName, content, comment = '//') { |
379
|
|
|
log.bright.cyan ('Transpiling ' + oldName.yellow + ' → ' + newName.yellow) |
380
|
|
|
let fileContents = fs.readFileSync (oldName, 'utf8') |
381
|
|
|
fileContents = fileContents.split ("\n" + comment + "====") [0] |
382
|
|
|
fileContents += |
383
|
|
|
"\n" + comment + "==============================================================================\n" + |
384
|
|
|
content.join ("\n" + comment + "------------------------------------------------------------------------------\n") |
385
|
|
|
fs.truncateSync (newName) |
386
|
|
|
fs.writeFileSync (newName, fileContents) |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
//----------------------------------------------------------------------------- |
390
|
|
|
|
391
|
|
|
function copyFile (oldName, newName) { |
392
|
|
|
let contents = fs.readFileSync (oldName, 'utf8') |
393
|
|
|
fs.truncateSync (newName) |
394
|
|
|
fs.writeFileSync (newName, contents) |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
//----------------------------------------------------------------------------- |
398
|
|
|
|
399
|
|
|
transpile ('./ccxt/exchanges.py', './ccxt/exchanges.py', python, '#') |
400
|
|
|
transpile ('./ccxt/async/exchanges.py', './ccxt/async/exchanges.py', pythonAsync, '#') |
401
|
|
|
transpile ('./ccxt.php', './build/ccxt.php', php, '//') |
402
|
|
|
|
403
|
|
|
//----------------------------------------------------------------------------- |
404
|
|
|
|
405
|
|
|
log.bright.green ('Transpiled successfully.') |
406
|
|
|
|